import { Body, Controller, Delete, Get, Param, Post, Put, Req } from '@nestjs/common';
import { BaseController } from '../../base/base.controller';
import { DictionaryService } from './dictionary.service';
import { DtoPipe } from '../../pipes/dto/dto.pipe';
import { DictionaryCategory } from '@app/db/common/entities/DictionaryCategory';
import { DictionaryItem } from '@app/db/common/entities/DictionaryItem';
import { AddCateogryDto, EditCategoryDto } from './dto/Category.dto';
import { AddItemDto, EditItemDto } from './dto/Item.dto';

@Controller('dictionary')
export class DictionaryController extends BaseController{
    constructor(
        private readonly service:DictionaryService
    ) {
        super()
    }

    @Get('list')
    async list() {
        const categorys = await this.service.db.dictionaryCategory.find()
        const items = await this.service.db.dictionaryItem.find()
        return this.successRes({categorys : categorys, items : items})
    }

    @Get('category/list')
    async categoryList() {
        const list = await this.service.db.dictionaryCategory.find()
        return this.successRes(list)
    }

    @Post('add/category')
    async addCategory(@Body(new DtoPipe()) dto:AddCateogryDto, @Req() { locale }) {
        if((await this.service.db.dictionaryCategory.isExistsByWhere({name : dto.name}))) return this.failRes(this.i18n.t(locale, 'nameIsExists'))
        if((await this.service.db.dictionaryCategory.isExistsByWhere({code : dto.code}))) return this.failRes(this.i18n.t(locale, 'codeIsExists'))
        const res = await this.service.db.dictionaryCategory.insert(dto)
        return res === null ? this.failRes() : this.successRes(res.rows)
    }

    @Put('edit/category/:id')
    async editCategory(@Param('id') id:number, @Body(new DtoPipe()) dto:EditCategoryDto, @Req() { locale }) {
        const category = await this.service.db.dictionaryCategory.findOne({id : id})
        if(!category) return this.failRes()
        let updateData:{[key in keyof DictionaryCategory]? : DictionaryCategory[key]} = {}
        if(category.name != dto.name) {
            updateData.name = dto.name
        }
        if(category.code != dto.code) {
            updateData.code = dto.code
        }

        if((Object.keys(updateData)).length == 0) return this.successRes()

        if(updateData.name && (await this.service.db.dictionaryCategory.isExistsByWhere({name : dto.name}))) return this.failRes(this.i18n.t(locale, 'nameIsExists'))
        if(updateData.code && (await this.service.db.dictionaryCategory.isExistsByWhere({code : dto.code}))) return this.failRes(this.i18n.t(locale, 'codeIsExists'))

        const res = await this.service.db.dictionaryCategory.update({id : id}, updateData)
        return res === 0 ? this.failRes() : this.successRes()
    }

    @Delete('delete/category/:id')
    async deleteCategory(@Param('id') id:number, @Req() { locale }) {
        if((await this.service.db.dictionaryItem.isExistsByWhere({categoryId : id}))) return this.failRes(this.i18n.t(locale, 'categoryHasChildNotDel'))
        const res = await this.service.db.dictionaryCategory.delete({id : id})
        return res === 0 ? this.failRes() : this.successRes()
    }


    @Get('item/list')
    async itemList() {
        const list = await this.service.db.dictionaryItem.find()
        return this.successRes(list)
    }

    @Post('add/item')
    async addItem(@Body(new DtoPipe()) dto:AddItemDto, @Req() { locale }) {
        if((await this.service.db.dictionaryItem.isExistsByWhere({parentId : dto.parentId || 0, categoryId : dto.categoryId, name : dto.name}))) return this.failRes(this.i18n.t(locale, 'nameIsExists'))
        if((await this.service.db.dictionaryItem.isExistsByWhere({parentId : dto.parentId || 0, categoryId : dto.categoryId, code : dto.code}))) return this.failRes(this.i18n.t(locale, 'codeIsExists'))
        const res = await this.service.db.dictionaryItem.insert(dto)
        return res === null ? this.failRes() : this.successRes(res.rows)
    }

    @Put('edit/item/:id')
    async edit(@Param('id') id:number, @Body(new DtoPipe({skipMissingProperties : true})) dto:EditItemDto, @Req() { locale }) {
        const item = await this.service.db.dictionaryItem.findOne({id : id})
        if(!item) return this.failRes()
        let updateData:{[key in keyof DictionaryItem]? : DictionaryItem[key]} = {}
        if(item.name != dto.name) {
            updateData.name = dto.name
        }
        if(item.code != dto.code) {
            updateData.code = dto.code
        }

        if((Object.keys(updateData)).length == 0) return this.successRes()

        if(updateData.name && (await this.service.db.dictionaryItem.isExistsByWhere({parentId : item.parentId, categoryId : item.categoryId, name : dto.name}))) return this.failRes(this.i18n.t(locale, 'nameIsExists'))
        if(updateData.code && (await this.service.db.dictionaryItem.isExistsByWhere({parentId : item.parentId, categoryId : item.categoryId, code : dto.code}))) return this.failRes(this.i18n.t(locale, 'codeIsExists'))
        

        const res = await this.service.db.dictionaryItem.update({id : id}, updateData)
        return res === 0 ? this.failRes() : this.successRes()
    }

    @Delete('delete/item/:id')
    async deleteItem(@Param('id') id:number, @Req() { locale }) {
        if((await this.service.db.dictionaryItem.isExistsByWhere({parentId : id}))) return this.failRes(this.i18n.t(locale, 'dictHasChildNotDel'))
        const res = await this.service.db.dictionaryItem.delete({id : id})
        return res === 0 ? this.failRes() : this.successRes()
    }

    @Get('getItemsByCategory/:categoryCode/')
    async getItemsByCategory(@Param('categoryCode') categoryCode:string) {
        const items = await this.service.getItemByCategory(categoryCode)
        return this.successRes(items)
    }
}
